#include <iostream>
#include <cstring>
#include <cerrno>
#include <string>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "ThreadPool.hpp"

void Usage(std::string s){
    std::cout << "Usage :" << "\n\t" << s << " port " << std::endl;
}


void ServiceIO(int sock){
    //提供服务
        while (true){
            char buffer[1024];
            memset(buffer, 0, sizeof(buffer));
            ssize_t s = read(sock, buffer, sizeof(buffer) - 1);
            if (s > 0){
                //将获取的内容当作字符串
                buffer[s] = 0;
                std::cout << "client# " << buffer << std::endl;
                std::string echo_string = ">>>server<<<";
                echo_string += buffer;
                echo_string += "...";
                write(sock, echo_string.c_str(), echo_string.size());
            }
            else if (s == 0){
                std::cout << "client quit ..." << std::endl;
                break;
            }
            else {
                std::cerr << "read errno" << errno << std::endl;
                break;
            }
        }
}


void *HandlerRequest(void* args){
    pthread_detach(pthread_self());
    int sock = *(int*)args;
    delete (int*)args;
    ServiceIO(sock);
    close(sock);
}

int main(int argc, char* argv[]){
    if (argc != 2){
        Usage(argv[0]);
        return 1;
    }
    
    //1.创建套接字
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock < 0){
        std::cerr << "socket create errno" << errno << std::endl;
        return 2;
    }
    std::cout << "listen_socket create success" << std::endl;
    //2.bind
    uint16_t port = atoi(argv[1]);
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_port = htons(port);
    local.sin_family = AF_INET;

    if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
        std::cerr << "bind errno" << errno << std::endl;
        return 3;
    }
    std::cout << "bind success" << std::endl;

    //3.因为tcp是面向连接的，所以在通信之前必须要建立连接
    //连接一定是有人主动建立(客户端)，一定有人被动接收连接(服务器)
    const int back_log = 5;
    if (listen(listen_sock, back_log) < 0){
        std::cerr << "listen error" << std::endl;
        return 4;
    }
    // signal(SIGCHLD, SIG_IGN); // 在Linux中父进程忽略子进程的SIGCHILD信号，子进程会自动退出释放资源
    //accept 
    for ( ; ; ){
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
        if (new_sock < 0){
            continue;   
        }
        uint16_t cli_port = ntohs(peer.sin_port);
        std::string cli_ip = inet_ntoa(peer.sin_addr);

        std::cout << "get a link cli_ip = " << cli_ip << "cli_port = " << cli_port << std::endl; 
        // pthread_t tid;
        // int *pram = new int(new_sock);
        // pthread_create(&tid, nullptr, HandlerRequest, pram);

        Task t(new_sock);
        ThreadPool::GetInstance()->InitThreadPool();
        ThreadPool::GetInstance()->PushTask(new_sock);
        //多进程版本
        // pid_t id = fork();
        // if (id  < 0){
        //     continue;
        // }
        // else if (id == 0){
        //     //child 
        //     close(listen_sock);
        //     ServiceIO(new_sock); //提供服务
        //     close(new_sock);
        //     exit(0);
        // }
        // else {
        //     //father
        //     close(new_sock);
        // }
    }
}
